ini.js ➔ decode   B
last analyzed

Complexity

Conditions 1
Paths 192

Size

Total Lines 73
Code Lines 49

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 49
nc 192
nop 1
dl 0
loc 73
rs 8.669
c 0
b 0
f 0

3 Functions

Rating   Name   Duplication   Size   Complexity  
F ini.js ➔ ... ➔ lines.forEach 0 35 14
B ini.js ➔ ... ➔ Object.filter 0 22 6
A ini.js ➔ ... ➔ Object.forEach 0 3 1

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
exports.parse = exports.decode = decode
2
3
exports.stringify = exports.encode = encode
4
5
exports.safe = safe
6
exports.unsafe = unsafe
7
8
var eol = typeof process !== 'undefined' &&
9
  process.platform === 'win32' ? '\r\n' : '\n'
10
11
function encode (obj, opt) {
12
  var children = []
13
  var out = ''
14
15
  if (typeof opt === 'string') {
16
    opt = {
17
      section: opt,
18
      whitespace: false
19
    }
20
  } else {
21
    opt = opt || {}
22
    opt.whitespace = opt.whitespace === true
23
  }
24
25
  var separator = opt.whitespace ? ' = ' : '='
26
27
  Object.keys(obj).forEach(function (k, _, __) {
0 ignored issues
show
Unused Code introduced by
The parameter _ is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter __ is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
28
    var val = obj[k]
29
    if (val && Array.isArray(val)) {
30
      val.forEach(function (item) {
31
        out += safe(k + '[]') + separator + safe(item) + '\n'
32
      })
33
    } else if (val && typeof val === 'object') {
34
      children.push(k)
35
    } else {
36
      out += safe(k) + separator + safe(val) + eol
37
    }
38
  })
39
40
  if (opt.section && out.length) {
41
    out = '[' + safe(opt.section) + ']' + eol + out
42
  }
43
44
  children.forEach(function (k, _, __) {
0 ignored issues
show
Unused Code introduced by
The parameter _ is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter __ is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
45
    var nk = dotSplit(k).join('\\.')
46
    var section = (opt.section ? opt.section + '.' : '') + nk
47
    var child = encode(obj[k], {
48
      section: section,
49
      whitespace: opt.whitespace
50
    })
51
    if (out.length && child.length) {
52
      out += eol
53
    }
54
    out += child
55
  })
56
57
  return out
58
}
59
60
function dotSplit (str) {
61
  return str.replace(/\1/g, '\u0002LITERAL\\1LITERAL\u0002')
62
    .replace(/\\\./g, '\u0001')
63
    .split(/\./).map(function (part) {
64
      return part.replace(/\1/g, '\\.')
65
      .replace(/\2LITERAL\\1LITERAL\2/g, '\u0001')
66
    })
67
}
68
69
function decode (str) {
70
  var out = {}
71
  var p = out
72
  var section = null
0 ignored issues
show
Unused Code introduced by
The assignment to section seems to be never used. If you intend to free memory here, this is not necessary since the variable leaves the scope anyway.
Loading history...
73
  //          section     |key      = value
74
  var re = /^\[([^\]]*)\]$|^([^=]+)(=(.*))?$/i
75
  var lines = str.split(/[\r\n]+/g)
76
77
  lines.forEach(function (line, _, __) {
0 ignored issues
show
Unused Code introduced by
The parameter _ is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter __ is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
78
    if (!line || line.match(/^\s*[;#]/)) return
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
79
    var match = line.match(re)
80
    if (!match) return
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
81
    if (match[1] !== undefined) {
82
      section = unsafe(match[1])
83
      p = out[section] = out[section] || {}
84
      return
85
    }
86
    var key = unsafe(match[2])
87
    var value = match[3] ? unsafe(match[4]) : true
88
    switch (value) {
89
      case 'true':
90
      case 'false':
91
      case 'null': value = JSON.parse(value)
92
    }
93
94
    // Convert keys with '[]' suffix to an array
95
    if (key.length > 2 && key.slice(-2) === '[]') {
96
      key = key.substring(0, key.length - 2)
97
      if (!p[key]) {
98
        p[key] = []
99
      } else if (!Array.isArray(p[key])) {
100
        p[key] = [p[key]]
101
      }
102
    }
103
104
    // safeguard against resetting a previously defined
105
    // array by accidentally forgetting the brackets
106
    if (Array.isArray(p[key])) {
107
      p[key].push(value)
108
    } else {
109
      p[key] = value
110
    }
111
  })
112
113
  // {a:{y:1},"a.b":{x:2}} --> {a:{y:1,b:{x:2}}}
114
  // use a filter to return the keys that have to be deleted.
115
  Object.keys(out).filter(function (k, _, __) {
116
    if (!out[k] ||
117
      typeof out[k] !== 'object' ||
118
      Array.isArray(out[k])) {
119
      return false
120
    }
121
    // see if the parent section is also an object.
122
    // if so, add it to that, and mark this one for deletion
123
    var parts = dotSplit(k)
124
    var p = out
125
    var l = parts.pop()
126
    var nl = l.replace(/\\\./g, '.')
127
    parts.forEach(function (part, _, __) {
0 ignored issues
show
Unused Code introduced by
The parameter _ is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter __ is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
128
      if (!p[part] || typeof p[part] !== 'object') p[part] = {}
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
129
      p = p[part]
130
    })
131
    if (p === out && nl === l) {
132
      return false
133
    }
134
    p[nl] = out[k]
135
    return true
136
  }).forEach(function (del, _, __) {
0 ignored issues
show
Unused Code introduced by
The parameter __ is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter _ is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
137
    delete out[del]
138
  })
139
140
  return out
141
}
142
143
function isQuoted (val) {
144
  return (val.charAt(0) === '"' && val.slice(-1) === '"') ||
145
    (val.charAt(0) === "'" && val.slice(-1) === "'")
146
}
147
148
function safe (val) {
149
  return (typeof val !== 'string' ||
150
    val.match(/[=\r\n]/) ||
151
    val.match(/^\[/) ||
152
    (val.length > 1 &&
153
     isQuoted(val)) ||
154
    val !== val.trim())
155
      ? JSON.stringify(val)
156
      : val.replace(/;/g, '\\;').replace(/#/g, '\\#')
157
}
158
159
function unsafe (val, doUnesc) {
0 ignored issues
show
Unused Code introduced by
The parameter doUnesc is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
160
  val = (val || '').trim()
161
  if (isQuoted(val)) {
162
    // remove the single quotes before calling JSON.parse
163
    if (val.charAt(0) === "'") {
164
      val = val.substr(1, val.length - 2)
165
    }
166
    try { val = JSON.parse(val) } catch (_) {}
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
167
  } else {
168
    // walk the val to find the first not-escaped ; character
169
    var esc = false
170
    var unesc = ''
171
    for (var i = 0, l = val.length; i < l; i++) {
172
      var c = val.charAt(i)
173
      if (esc) {
174
        if ('\\;#'.indexOf(c) !== -1) {
175
          unesc += c
176
        } else {
177
          unesc += '\\' + c
178
        }
179
        esc = false
180
      } else if (';#'.indexOf(c) !== -1) {
181
        break
182
      } else if (c === '\\') {
183
        esc = true
184
      } else {
185
        unesc += c
186
      }
187
    }
188
    if (esc) {
189
      unesc += '\\'
190
    }
191
    return unesc.trim()
192
  }
193
  return val
194
}
195